001    /*
002     * Copyright 2006 Stephen J. McConnell.
003     *
004     * Licensed  under the  Apache License,  Version 2.0  (the "License");
005     * you may not use  this file  except in  compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *   http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed  under the  License is distributed on an "AS IS" BASIS,
012     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
013     * implied.
014     *
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package net.dpml.metro.builder;
020    
021    import java.io.IOException;
022    import java.io.OutputStream;
023    import java.io.OutputStreamWriter;
024    import java.io.Writer;
025    
026    import javax.xml.XMLConstants;
027    
028    import net.dpml.metro.info.Type;
029    import net.dpml.metro.info.InfoDescriptor;
030    import net.dpml.metro.info.ContextDescriptor;
031    import net.dpml.metro.info.CategoryDescriptor;
032    import net.dpml.metro.info.ServiceDescriptor;
033    import net.dpml.metro.info.EntryDescriptor;
034    import net.dpml.metro.info.Descriptor;
035    
036    import net.dpml.state.State;
037    import net.dpml.state.StateEncoder;
038    
039    /**
040     * Type builder.
041     *
042     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
043     * @version 1.0.1
044     */
045    public class ComponentTypeEncoder
046    {
047        private static final String XML_HEADER = 
048          "<?xml version=\"1.0\"?>";
049        
050        private static final String PART_SCHEMA_URN = "link:xsd:dpml/lang/dpml-part#1.0";
051        private static final String TYPE_SCHEMA_URN = "link:xsd:dpml/lang/dpml-type#1.0";
052        private static final StateEncoder STATE_GRAPH_ENCODER = new StateEncoder();
053            
054        private static final String HEADER = 
055          "<type xmlns=\"" 
056          + TYPE_SCHEMA_URN 
057          + "\""
058          + "\n    xmlns:xsi=\"" 
059          + XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI
060          + "\"\n    xmlns:part=\"" 
061          + PART_SCHEMA_URN
062          + "\"\n    xmlns:type=\"" 
063          + TYPE_SCHEMA_URN
064          + "\">";
065    
066        private static final String FOOTER = "</type>";
067        
068       /**
069        * Write the supplied type to an output stream.
070        * @param type the type descriptor
071        * @param output the output stream
072        * @exception IOException if an IO error occurs
073        */
074        public void export( Type type, OutputStream output ) throws IOException
075        {
076            final Writer writer = new OutputStreamWriter( output );
077            writer.write( XML_HEADER );
078            writer.write( "\n\n" );
079            writer.write( HEADER );
080            writer.write( "\n" );
081            writeBody( writer, type, "  " );
082            writer.write( "\n" );
083            writer.write( FOOTER );
084            writer.write( "\n" );
085            writer.flush();
086            output.close();
087        }
088        
089        private void writeBody( Writer writer, Type type, String pad ) throws IOException
090        {
091            writeTypeInfo( writer, type.getInfo(), pad );
092            writeTypeServices( writer, type.getServiceDescriptors(), pad );
093            writeTypeContext( writer, type.getContextDescriptor(), pad );
094            writeTypeCategories( writer, type.getCategoryDescriptors(), pad );
095            writeTypeState( writer, type.getStateGraph(), pad );
096        }
097        
098        private void writeTypeInfo( Writer writer, InfoDescriptor info, String pad ) throws IOException
099        {
100            writer.write( "\n" + pad + "<info" );
101            writer.write( " name=\"" + info.getName() );
102            writer.write( "\"\n" + pad + "    class=\"" + info.getClassname() );
103            writer.write( "\"\n" + pad + "    version=\"" + info.getVersion() );
104            writer.write( "\"\n" + pad + "    lifestyle=\"" + info.getLifestylePolicy().getName().toLowerCase() );
105            writer.write( "\"\n" + pad + "    collection=\"" + info.getCollectionPolicy().getName().toLowerCase() );
106            writer.write( "\"\n" + pad + "    threadsafe=\"" + info.getThreadSafePolicy().getName().toLowerCase() );
107            writer.write( "\"" );
108            if( info.getAttributeNames().length > 0 )
109            {
110                writer.write( ">" );
111                writeAttributes( writer, info, pad + "  " );
112                writer.write( "\n" + pad + "</info>" );
113            }
114            else
115            {
116                writer.write( "/>" );
117            }
118        }
119    
120        private void writeTypeServices( Writer writer, ServiceDescriptor[] services, String pad ) throws IOException
121        {
122            if( services.length == 0 )
123            {
124                return;
125            }
126            else
127            {
128                writer.write( "\n" + pad + "<services>" );
129                for( int i=0; i<services.length; i++ )
130                {
131                    ServiceDescriptor service = services[i];
132                    writer.write( "\n" + pad + "  <service" );
133                    writer.write( " class=\"" + service.getClassname() );
134                    writer.write( "\" version=\"" + service.getVersion() );
135                    writer.write( "\"/>" );
136                }
137                writer.write( "\n" + pad + "</services>" );
138            }
139        }
140        
141        private void writeTypeContext( Writer writer, ContextDescriptor context, String pad ) throws IOException
142        {
143            EntryDescriptor[] entries = context.getEntryDescriptors();
144            if( entries.length > 0 )
145            {
146                writer.write( "\n" + pad + "<context>" );
147                for( int i=0; i<entries.length; i++ )
148                {
149                    EntryDescriptor entry = entries[i];
150                    writer.write( "\n" + pad + "  <entry" );
151                    writer.write( " key=\"" + entry.getKey() );
152                    writer.write( "\" class=\"" + entry.getClassname() );
153                    if( entry.isOptional() )
154                    {
155                        writer.write( "\" optional=\"true\"" );
156                    }
157                    else
158                    {
159                        writer.write( "\" optional=\"false\"" );
160                    }
161                    if( entry.isVolatile() )
162                    {
163                        writer.write( "\" volatile=\"true\"" );
164                    }
165                    writer.write( "/>" );
166                }
167                writer.write( "\n" + pad + "</context>" );
168            }
169            else
170            {
171                return;
172            }
173        }
174        
175        private void writeTypeCategories( 
176          Writer writer, CategoryDescriptor[] categories, String pad ) throws IOException
177        {
178            if( categories.length > 0 )
179            {
180                writer.write( "\n" + pad + "<categories>" );
181                for( int i=0; i<categories.length; i++ )
182                {
183                    CategoryDescriptor category = categories[i];
184                    writer.write( "\n" + pad + "  <category" );
185                    writer.write( " name=\"" + category.getName() );
186                    writer.write( 
187                      "\" priority=\"" 
188                      + category.getDefaultPriority().getName().toLowerCase() );
189                    writer.write( "\"" );
190    
191                    if( category.getAttributeNames().length > 0 )
192                    {
193                        writer.write( ">" );
194                        writeAttributes( writer, category, pad + "    " );
195                        writer.write( "\n" + pad + "  </category>" );
196                    }
197                    else
198                    {
199                        writer.write( "/>" );
200                    }
201                }
202                writer.write( "\n" + pad + "</categories>" );
203            }
204            else
205            {
206                return;
207            }
208        }
209        
210        private void writeTypeState( Writer writer, State state, String pad ) throws IOException
211        {
212            STATE_GRAPH_ENCODER.writeState( writer, state, pad );
213            writer.write( "\n" );
214        }
215        
216        private void writeAttributes( Writer writer, Descriptor descriptor, String pad ) throws IOException
217        {
218            String[] names = descriptor.getAttributeNames();
219            for( int i=0; i<names.length; i++ )
220            {
221                String name = names[i];
222                String value = descriptor.getAttribute( name, "" );
223                writer.write( "\n" + pad + "<property" );
224                writer.write( " name=\"" + name );
225                writer.write( "\" value=\"" + value );
226                writer.write( "\"/>" );
227            }
228        }
229    }
230